#
# This file is part of the kernelstudio package.
#
# (c) 2014-2025 zlin <admin@kernelstudio.com>
#
# For the full copyright and license information, please view the LICENSE file
# that was distributed with this source code.
import datetime
import logging
import uuid

from ksai.models.document_attachment import DocumentAttachmentModelQuery, DocumentAttachmentModel, DocumentStatus
from ksai.persistence.database import db
from ksai.persistence.storage.attachment import Attachment
from ksai.utils.strings import has_text

logger = logging.getLogger(__name__)


class DocumentAttachmentService:

    @staticmethod
    def find_by_query(query: DocumentAttachmentModelQuery) -> DocumentAttachmentModelQuery:
        q = (DocumentAttachmentModel.query.filter(DocumentAttachmentModel.deleted_at == None)
             .order_by(DocumentAttachmentModel.created_at.desc()))
        if has_text(query.keyword):
            search = f"%{query.keyword}%"
            q = q.filter(
                db.or_(
                    DocumentAttachmentModel.filename.ilike(search),
                    DocumentAttachmentModel.filepath.ilike(search),
                    DocumentAttachmentModel.original_name.ilike(search),
                    DocumentAttachmentModel.category.ilike(search),
                )
            )
        items = q.paginate(page=query.page, per_page=query.offset, error_out=False)
        query.pagination(items)
        return query

    @staticmethod
    def save_from_storage_file(attachment: Attachment):
        document = DocumentAttachmentModel()
        document.uuid = attachment.uuid
        document.filename = attachment.filename
        document.filepath = attachment.filepath
        document.size = attachment.size
        document.original_name = attachment.original_name
        document.mime = attachment.mime
        document.suffix = attachment.suffix
        document.category = attachment.category
        DocumentAttachmentService.save(document)
        return document

    @staticmethod
    def find_one_by_uuid(uuid_param: str) -> DocumentAttachmentModel:
        q = DocumentAttachmentModel.query.filter(DocumentAttachmentModel.deleted_at == None)
        return q.filter_by(uuid=str(uuid_param)).first()

    @staticmethod
    def _resolve(document: DocumentAttachmentModel):
        if document.uuid is None:
            document.uuid = str(uuid.uuid4())
        if document.created_at is None:
            document.created_at = datetime.datetime.now()
        if document.updated_at is None:
            document.updated_at = datetime.datetime.now()
        if document.status is None:
            document.status = DocumentStatus.UPLOADED.name

    @staticmethod
    def update_by_session(document: DocumentAttachmentModel, session=None):
        DocumentAttachmentService._resolve(document)
        # 如果未传入会话，使用默认会话
        if session is None:
            session = db.session
        try:
            # 检查是新增还是更新
            if document.id is None:
                session.add(document)
            else:
                # 确保对象在会话中
                if document not in session:
                    # 使用merge而不是add，避免对象状态冲突
                    session.merge(document)

            # 不要在这里commit，由调用方控制事务
            session.flush()  # 刷新但不要提交
            return document
        except Exception as e:
            # 不要在这里rollback，由调用方控制事务
            logger.error(f"Failed to save document: {str(e)}")
            raise

    @staticmethod
    def save(document: DocumentAttachmentModel) -> bool:
        DocumentAttachmentService._resolve(document)
        db.session.add(document)
        db.session.commit()
        return True
